package kunsch.read;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import kunsch.bexp.And;
import kunsch.bexp.BooleanFunction;
import kunsch.bexp.Expression;
import kunsch.bexp.Not;
import kunsch.bexp.Or;
import kunsch.bexp.Variable;
import kunsch.bexp.util.BExpUtil;

public class BLIFReader {

	private Variable lastOutVariable;

	List<BooleanFunction> readFunctions = new ArrayList<BooleanFunction>();
	List<Variable> lastVariables;

	public void readFiles(String folderPath) {

		File blifFolder = new File(folderPath);
		for (File file : blifFolder.listFiles()) {
			readFile(file);
		}

		/*
		 * for (BooleanFunction function : getReadFunctions()) {
		 * System.out.println(function); }
		 */

	}

	/**
	 * reads the content of a blif file until ".names" appears. after that the
	 * given variables after .names (e.g. .names a b c d x) are created and the
	 * following lines are parsed.
	 * 
	 * @param file
	 */
	public BooleanFunction readFile(File file) {
		boolean beginFound = false;

		List<Expression> andList = new ArrayList<Expression>();

		lastVariables = new ArrayList<Variable>();

		try {
			BufferedReader reader = new BufferedReader(new FileReader(file));
			String line = reader.readLine();
			while (line != null) {
				// is boolean function description begin
				if (line.startsWith(".names")) {
					beginFound = true;
					String[] splitted = line.split(" ");
					for (String s : splitted) {
						if (!s.equals(".names")) {
							lastVariables.add(new Variable(s));
						}
					}
				} else if (beginFound) {
					andList.add(readAndLine(line));
				}

				line = reader.readLine();
			}
			reader.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		BooleanFunction newFunction = new BooleanFunction(lastOutVariable,
				new Or(andList), lastVariables);
		readFunctions.add(newFunction);
		return newFunction;
	}

	/**
	 * parses the given line and set the lastAndExpr field with the result
	 * 
	 * @param line
	 *            a blif line. e.g. "1--0 1"
	 */
	private Expression readAndLine(String line) {
		List<Expression> variableList = new ArrayList<Expression>();

		String[] splitted = line.split(" ");
		char[] inValues = splitted[0].toCharArray();

		if (lastOutVariable == null) {
			lastOutVariable = lastVariables.get(lastVariables.size() - 1);
			lastVariables.remove(lastVariables.size() - 1);
		}

		for (int i = 0; i < inValues.length; i++) {
			char c = inValues[i];

			if (c != '-') {
				Expression actExpression = BExpUtil
						.copyExpression(lastVariables.get(i));
				if (c == '0')
					actExpression = new Not(actExpression);

				variableList.add(actExpression);

			}
		}

		return new And(variableList);
	}

	public List<BooleanFunction> getReadFunctions() {
		return readFunctions;
	}
}
